package com.glodon.paas.qto.service.impl;

import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;

import com.glodon.paas.exception.PaasServerExceptionFactory;
import com.glodon.paas.job.JobConstants;
import com.glodon.paas.job.exception.JsonException;
import com.glodon.paas.job.model.TaskStatus;
import com.glodon.paas.job.util.JsonUtil;
import com.glodon.paas.qto.model.TaskProgress;
import com.glodon.paas.qto.service.DispatcherService;

/**
 * 将Task下发给job server
 * 
 * @author botao.liao
 * 
 */
@Service
public class DispatcherServiceImpl implements DispatcherService {
    private final Logger logger = LoggerFactory.getLogger(getClass());
    @Autowired
    private RestTemplate template = new RestTemplate();

    @Value("${job.task.url}")
    private String jobServerUrl;
    @Value("${qto.callback.url}")
    private String qtoCallbackUrl;

    @Override
    @SuppressWarnings({ "rawtypes", "unchecked" })
    public String dispath(String function, Map params) {
        String url = getJobServerUrl() + "/{function}";
        String json;
        try {
            params.put(JobConstants.TASK_CALLBACK, qtoCallbackUrl.trim());
            logger.info("send to job-server: {}", JsonUtil.objectToJson(params));
            json = template.postForObject(url, params, String.class, function);
        } catch (RestClientException e) {
            throw PaasServerExceptionFactory.internalAPIException("submit task '" + function + "' failed.", e);
        }
        logger.info("send task '{}' to job server, response:{}", function, json);
        String jobServerTaskId = parseJobServerTaskId(json);
        return jobServerTaskId;
    }

    @SuppressWarnings("rawtypes")
    @Override
    public TaskProgress queryTaskProgress(String jobServerTaskId) {
        String url = getJobServerUrl() + "/{taskId}";
        try {
            String json = template.getForObject(url, String.class, jobServerTaskId);
            logger.debug("query task status from job-server:{}", json);
            Map map = null;
            try {
                map = JsonUtil.jsonToMap(json);
            } catch (JsonException e) {
                throw PaasServerExceptionFactory.validateException("bad json string from job-server", e);
            }
            TaskProgress task = new TaskProgress();
            task.setTaskId(jobServerTaskId);
            String status = (String) map.get(JobConstants.PROPERTY_TASK_STATUS);
            if (StringUtils.isEmpty(status)) {
                throw PaasServerExceptionFactory.validateException("status cann't be empty", null);
            }
            task.setProgress((Integer) ((Map) map.get("values")).get("progress"));
            task.setMessage((String) ((Map) map.get("values")).get(JobConstants.TASK_MESSAGE));
            task.setStatus(Enum.valueOf(TaskStatus.class, status));
            task.setOutput((String) ((Map) map.get("values")).get(JobConstants.OUTPUT));
            task.setFilename((String) ((Map) map.get("values")).get(JobConstants.PROPERTY_TASK_FILE_NAME));
            return task;
        } catch (HttpClientErrorException e) {
            logger.error(e.getMessage(), e);
        } catch (RestClientException e) {
            logger.error("query task progress failed:" + jobServerTaskId, e);
        }
        return null;
    }

    @SuppressWarnings("rawtypes")
    private String parseJobServerTaskId(String json) {

        if (StringUtils.isEmpty(json)) {
            throw PaasServerExceptionFactory.validateException("bad json string from job-server,json is null", null);
        }

        Map result = null;
        try {
            result = JsonUtil.jsonToMap(json);
        } catch (JsonException e) {
            throw PaasServerExceptionFactory.validateException("bad json string from job-server", e);
        }

        String errorMsg = (String) result.get(JobConstants.ERROR_MSG);
        if (!StringUtils.isEmpty(errorMsg)) {
            throw PaasServerExceptionFactory.internalAPIException("job server Error:" + errorMsg, null);
        } else {
            return (String) result.get(JobConstants.PROPERTY_TASK_ID);
        }
    }

    /**
     * job Server的Url地址.
     * 
     * @param jobServerUrl
     */
    public void setJobServerUrl(String jobServerUrl) {
        this.jobServerUrl = jobServerUrl;
    }

    public void setTemplate(RestTemplate template) {
        this.template = template;
    }

    public String getJobServerUrl() {
        return jobServerUrl;
    }

    public void setQtoCallbackUrl(String qtoCallbackUrl) {
        this.qtoCallbackUrl = qtoCallbackUrl;
    }
}
